#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hal_bsp_wifi.h"
#include "hal_bsp_mqtt.h"
#include "hal_bsp_ap3216c.h"
#include "hal_bsp_aw2013.h"
#include "hal_bsp_pcf8574.h"
#include "hal_bsp_sht20.h"
#include "hal_bsp_ssd1306.h"
#include "hal_bsp_structAll.h"
#include "hal_bsp_log.h"
#include "cJSON.h"
#include "iot_gpio.h"
#include "iot_watchdog.h"
#include "iot_pwm.h"
#include "hi_io.h"
#include "hi_adc.h"
#include "hi_errno.h"
// 设备ID
#define DEVICE_ID                           "your_device_id"
// MQTT客户端ID
#define MQTT_CLIENT_ID                      "your_mqtt_client_id"
// MQTT用户名
#define MQTT_USER_NAME                      "your_mqtt_user_name"
// MQTT密码
#define MQTT_PASS_WORD                      "your_mqtt_pass_word"
// 华为云平台的IP地址
#define SERVER_IP_ADDR                      "your_server_ip_addr"   
// 华为云平台的IP端口号
#define SERVER_IP_PORT                      1883       

// 订阅 接收控制命令的主题
#define MQTT_TOPIC_SUB_COMMANDS             "$oc/devices/%s/sys/commands/#" 
// 发布 成功接收到控制命令后的主题
#define MQTT_TOPIC_PUB_COMMANDS_REQ         "$oc/devices/%s/sys/commands/response/request_id=%s"  
#define MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ  "$oc/devices//sys/commands/response/request_id="  

// 发布 设备属性数据的主题
#define MQTT_TOPIC_PUB_PROPERTIES           "$oc/devices/%s/sys/properties/report"        
#define MALLOC_MQTT_TOPIC_PUB_PROPERTIES    "$oc/devices//sys/properties/report"        
#define MQTT_PAYLOAD_PUB                    "{\"services\":[{\"service_id\":\"attribute\",\"properties\":{\"zhongtong\":\"%d\",\"yuantong\":\"%d\",\"shunfeng\":\"%d\",\"judge\":\"%s\"}}]}"
#define IOT_GPIO_KEY  5
#define MsgQueueObjectNumber 16       // 定义消息队列对象的个数
typedef struct message_sensorData
{
  int zhongtong;
  int yuantong;
  int shunfeng;
  uint8_t judge;
}msg_sensorData_t;
msg_sensorData_t sensorData = {0};    // 传感器的数据

tn_pcf8574_io_t pcf8574_io;
#define IO_JUDGE  pcf8574_io.bit.p0

osThreadId_t mqtt_send_task_id; // mqtt 发布数据任务ID
osThreadId_t mqtt_recv_task_id; // mqtt 接收数据任务ID

int ZTKD=0;
int YTKD=0;
int SFKD=0;

//获取系统时间，用于执行中断
clock_t time1 ,time2;
//根据time1和time2计算时间间隔
double duration;

/**
 * @brief 获取电压值函数
 * 
 * @return 电压值 
 */

static float GetVoltage(void)
{
    unsigned int ret;
    unsigned short data;

    // 该函数通过使用hi_adc_read()函数来读取 HI_ADC_CHANNEL_2 的数值存储在data中， 
    // HI_ADC_EQU_MODEL_8 表示8次平均算法模式，
    // HI_ADC_CUR_BAIS_DEFAULT 表示默认的自动识别模式，
    ret = hi_adc_read((hi_adc_channel_index)HI_ADC_CHANNEL_2, &data, 
                    HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0);
    if (ret != HI_ERR_SUCCESS) {
        printf("ADC Read Fail\n");
        return;
    }
    
    // 最后通过 data * 1.8 * 4 / 4096.0 计算出实际的电压值。
    return (float)data * 1.8 * 4 / 4096.0;
}

//设置中断
static void OnButtonPressed(char* arg)
{
	
  (void*)arg;
  float voltage;

  //计算与上一次中断的时间间隔duration
  time1 = time2;
  time2 = time(NULL);
  duration = ((double)(time2 - time1));

  //当duration大于0.5时执行中断效果
	if(duration > 0.5){
    voltage = GetVoltage();
		if(voltage < 3){
			printf("vlt:%.3fV\n", voltage);
		}
		//排队人数加一
		if((voltage > 0.01) && (voltage < 0.4))
		{
			printf("Number of Zhongtong Express reducing one\n");
      ZTKD--;
      printf("Number of Zhongtong Express is %d\n",ZTKD);
		}

    if((voltage >= 0.4) && (voltage <= 0.8))
    {
      printf("Number of Yuantong Express reducing one\n");
      YTKD--;
      printf("Number of Yuantong Express is %d\n",SFKD);
    }

    if((voltage > 0.8) && (voltage <= 1.2))
    {
      printf("Number of Shunfeng Express reducing one\n");
      SFKD--;
      printf("Number of Shunfeng Express is %d\n",YTKD);
    }
	}
}

/**
 * @brief MQTT  发布消息任务
 */
void mqtt_send_task(void *argument)
{
  uint8_t payloadBuffer[500] = {0};
  while(1)
  {
    sensorData.zhongtong = ZTKD;
    sensorData.yuantong = YTKD;
    sensorData.shunfeng = SFKD;
    sensorData.judge = IO_JUDGE;

    console_log_info("zhongtong:%d yuantong:%d shunfeng:%d", 
      sensorData.zhongtong,
      sensorData.yuantong,
      sensorData.shunfeng,
      sensorData.judge
    );

    char *publish_topic = (char *)malloc(strlen(MALLOC_MQTT_TOPIC_PUB_PROPERTIES) + strlen(DEVICE_ID) + 1);
    if(publish_topic != NULL)
    {
      memset(publish_topic, 0, strlen(DEVICE_ID) + strlen(MALLOC_MQTT_TOPIC_PUB_PROPERTIES) + 1);
      sprintf(publish_topic, MQTT_TOPIC_PUB_PROPERTIES, DEVICE_ID);
      
      memset(payloadBuffer, 0, sizeof(payloadBuffer));
      sprintf(payloadBuffer, MQTT_PAYLOAD_PUB, 
        sensorData.zhongtong,
        sensorData.yuantong,
        sensorData.shunfeng,
        sensorData.judge ? "ON" : "ZT-OFF"
      );
      MQTTClient_pub(publish_topic, payloadBuffer, strlen((char *)payloadBuffer));

      free(publish_topic);
      publish_topic = NULL;
    }
    else
      publish_topic = NULL;

    sleep(3);
  }
}

/**
 * @brief MQTT接收数据的回调函数
 */
int8_t mqttClient_sub_callback(unsigned char *topic, unsigned char *payload)
{
  if ((topic == NULL) || (payload == NULL))
    return -1;
  else 
  {
    console_log_info("topic: %s", topic);
    console_log_info("payload: %s", payload);

    // 提取出topic中的request_id
    char request_id[50] = {0};
    int ret_code = 1;   // 1为失败
    strcpy(request_id, topic + strlen(DEVICE_ID) + strlen("$oc/devices//sys/commands/request_id="));
    console_log_info("request_id: %s", request_id);
    
#if 1
    cJSON *root = NULL;
    cJSON *command_name = NULL;
    cJSON *paras = NULL;
    cJSON *value = NULL;
    cJSON *red = NULL;
    cJSON *green = NULL;
    cJSON *blue = NULL;

    root = cJSON_Parse((const char *)payload);
    if (root)// 解析JSON数据
    {
      command_name = cJSON_GetObjectItem(root, "command_name");
      paras = cJSON_GetObjectItem(root, "paras");
      if (command_name)
      {
        if (!strcmp(command_name->valuestring, "zhongtong"))
        {
          value = cJSON_GetObjectItem(paras, "value1");
          if (!strcmp(value->valuestring, "OUT"))
          {
            console_log_info("Anomaly occurs in Zhongtong");
            ZTKD--;
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "Clear"))
          {
            console_log_info("Clear out Zhongtong warehouse");
            ZTKD=0;
            ret_code = 0;   // 0为成功
          }
        }
        else if (!strcmp(command_name->valuestring, "yuantong"))
        {
          value = cJSON_GetObjectItem(paras, "value2");
          if (!strcmp(value->valuestring, "OUT"))
          {
            console_log_info("Anomaly occurs in Yuantong");
            YTKD--;
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "Clear"))
          {
            console_log_info("Clear out Yuantong warehouse");
            YTKD=0;
            ret_code = 0;   // 0为成功
          }
        }
        else if (!strcmp(command_name->valuestring, "shunfeng"))
        {
          value = cJSON_GetObjectItem(paras, "value3");
          if (!strcmp(value->valuestring, "OUT"))
          {
            console_log_info("Anomaly occurs in Shunfeng");
            SFKD--;
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "Clear"))
          {
            console_log_info("Clear out Shunfeng warehouse");
            SFKD=0;
            ret_code = 0;   // 0为成功
          }
        }
        else if (!strcmp(command_name->valuestring, "judge"))
        {
          value = cJSON_GetObjectItem(paras, "value");
          if (!strcmp(value->valuestring, "ON"))
          {
            IO_JUDGE = 1;
            PCF8574_Write(pcf8574_io.all);
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "ZT-OFF"))
          {
            console_log_info("This Zhongtong express is in trouble");
            IO_JUDGE = 0;
            PCF8574_Write(pcf8574_io.all);
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "YT-OFF"))
          {
            console_log_info("This Yuantong express is in trouble");
            IO_JUDGE = 0;
            PCF8574_Write(pcf8574_io.all);
            ret_code = 0;   // 0为成功
          }
          else if (!strcmp(value->valuestring, "SF-OFF"))
          {
            console_log_info("This Shunfeng express is in trouble");
            IO_JUDGE = 0;
            PCF8574_Write(pcf8574_io.all);
            ret_code = 0;   // 0为成功
          }
        }
      }

      // 向云端发送命令设置的返回值
      char *request_topic = (char*)malloc(strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + strlen(DEVICE_ID) + strlen(request_id) + 10);
      if(request_topic != NULL)
      {
        memset(request_topic, 0, strlen(DEVICE_ID) + strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + 10);
        sprintf(request_topic, MQTT_TOPIC_PUB_COMMANDS_REQ, DEVICE_ID, request_id);
        printf("topic: %s", request_topic);
        if(ret_code == 0){
          MQTTClient_pub(request_topic, "{\"result_code\":0}", strlen("{\"result_code\":0}"));
          console_log_info("data: %s", "{\"result_code\":0}");
        }
        else if(ret_code == 1){
          MQTTClient_pub(request_topic, "{\"result_code\":1}", strlen("{\"result_code\":1}"));
          console_log_info("data: %s", "{\"result_code\":1}");
        }
        free(request_topic);
      }
    }

    root = NULL;
    command_name = NULL;
    paras = NULL;
    value = NULL;
    red = NULL;
    green = NULL;
    blue = NULL;
#endif
  }
    
  return 0;
}

/**
 * @brief MQTT  接收消息任务
 */
void mqtt_recv_task(void *argument)
{
  while (1)
  {
    MQTTClient_sub();
    sleep(1);
  }
}

static void network_mqtt_example(void)
{
  IO_JUDGE = 1;
  p_MQTTClient_sub_callback = &mqttClient_sub_callback;

  // 连接WiFi
  if (WiFi_connectHotspots("your_wifi_ssid", "your_wifi_psk") != WIFI_SUCCESS)
  {
    console_log_error("connectWiFiHotspots");
  }
  else
  {
    sleep(1);
    console_log_info("connectWiFiHotspots");
  }

  // 连接MQTT服务器
  if (MQTTClient_connectServer(SERVER_IP_ADDR, SERVER_IP_PORT) != 0)
  {
    console_log_error(" mqttClient_connectServer");
    sleep(2);
  }
  else
  {
    sleep(1);
    console_log_info("mqttClient_connectServer");
  }

  // 初始化MQTT客户端
  if (MQTTClient_init(MQTT_CLIENT_ID, MQTT_USER_NAME, MQTT_PASS_WORD) != 0)
  {
    console_log_error("mqttClient_init");
    sleep(2);
  }
  else
  {
    sleep(1);
    console_log_info("mqttClient_init");
  }

  // 订阅主题
  if (MQTTClient_subscribe(MQTT_TOPIC_SUB_COMMANDS) != 0)
  {
    console_log_error("mqttClient_subscribe");
    sleep(2);
  }
  else
  {
    sleep(1);
    console_log_info("mqttClient_subscribe");
  }
  // 设置中断
  IoTGpioInit(IOT_GPIO_KEY);
  hi_io_set_func(IOT_GPIO_KEY, HI_IO_FUNC_GPIO_5_GPIO);
  IoTGpioSetDir(IOT_GPIO_KEY, IOT_GPIO_DIR_IN);
  hi_io_set_pull(IOT_GPIO_KEY, HI_IO_PULL_UP);
  IoTGpioRegisterIsrFunc(IOT_GPIO_KEY, IOT_INT_TYPE_LEVEL, 
                          IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                          OnButtonPressed, NULL);

  //创建线程
  osThreadAttr_t options;
  options.name = "mqtt_send_task";
  options.attr_bits = 0;
  options.cb_mem = NULL;
  options.cb_size = 0;
  options.stack_mem = NULL;
  options.stack_size = 1024*10;
  options.priority = osPriorityNormal;
  //运行mqtt_send_task的线程，发送MQTT消息
  mqtt_send_task_id = osThreadNew((osThreadFunc_t)mqtt_send_task, NULL, &options);
  if (mqtt_send_task_id != NULL)
  {
    console_log_info("ID = %d, Create mqtt_send_task_id is OK!", mqtt_send_task_id);
  }
  options.name = "mqtt_recv_task";
  options.stack_size = 1024*10;
  //运行mqtt_recv_task的线程，接收MQTT消息
  mqtt_recv_task_id = osThreadNew((osThreadFunc_t)mqtt_recv_task, NULL, &options);
  if (mqtt_recv_task_id != NULL)
  {
    console_log_info("ID = %d, Create mqtt_recv_task_id is OK!", mqtt_recv_task_id);
  }
}

SYS_RUN(network_mqtt_example);